package co.liyao.credentials;

import co.liyao.model.User;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Auther: liyao
 * @Date: 2019/2/18 16:50
 * @Description:
 */
public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher {

    /**
     * 用户登录次数计数  redisKey 前缀
     */
    private static final String SHIRO_LOGIN_COUNT = "shiro_login_count_";

    /**
     * 用户登录是否被锁定    一小时 redisKey 前缀
     */
    private static final String SHIRO_IS_LOCK = "shiro_is_lock_";


    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        User sysUser=(User) info.getPrincipals().getPrimaryPrincipal();
        String username=sysUser.getUsername();

        String isLockKey = SHIRO_IS_LOCK + username;
        Boolean aBoolean = redisTemplate.hasKey(isLockKey);
        if(aBoolean){
            throw new ExcessiveAttemptsException("sorry，账号【"+username+"】已被禁止1小时内登陆！");
        }


        // 验证密码的正确
        Object tokenHashedCredentials = this.hashProvidedCredentials(token, info);
        Object accountCredentials = this.getCredentials(info);

        boolean bool = this.equals(tokenHashedCredentials, accountCredentials);
        //访问计数
        ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
        String loginCountKey = SHIRO_LOGIN_COUNT + username;

        if(!bool){

            valueOperations.increment(loginCountKey,1);  //自增

            String logcounts =String.valueOf(valueOperations.get(loginCountKey));
            if (Integer.parseInt(logcounts) >= 5 ){
                valueOperations.set(isLockKey,"LOCK");
                redisTemplate.expire(isLockKey,1, TimeUnit.HOURS);
                redisTemplate.expire(loginCountKey,1, TimeUnit.HOURS);
                redisTemplate.delete(loginCountKey);
                throw new ExcessiveAttemptsException("sorry，账号【"+username+"】已被禁止1小时内登陆！");
            }
            throw new AccountException("账号或密码不正确！你还有"+(5-Integer.parseInt(logcounts))+"次机会！");
        }else{
            redisTemplate.delete(isLockKey);
            redisTemplate.delete(loginCountKey);
        }
        return true;
    }
}
